package com.wl.cloud.common.annotation;

import cn.hutool.core.lang.Assert;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.List;

/**
 * @author: wanglin
 * @date: 2023-08-02 周三
 * @Version: 1.0
 * @Description:
 */
public class ValidatorUtil {

    /**
     * 注解验证测试
     *
     * @param o
     */
    public static void notBlank(Object o) {
        Field[] declaredFields = o.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            boolean annotationPresent = declaredField.isAnnotationPresent(NotBlankInList.class);
            if (annotationPresent) {
                NotBlankInList annotation = declaredField.getAnnotation(NotBlankInList.class);
                declaredField.setAccessible(true);

                String name = declaredField.getName();
                System.out.println(name);
                List<?> fieldValue = null;
                try {
                    Object valueObject = declaredField.get(o);
                    Assert.isNull(valueObject, name + "不能为空！");
                    fieldValue = (List<?>) declaredField.get(o);
                    Assert.isTrue(fieldValue.size() > 0, name + "不能为空！！");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                System.out.println(fieldValue);
                fieldValue.stream().forEach(e -> Assert.isTrue(!isEmptyIfStr(e), name + "不能为空!!!"));

            }
        }
    }

    /**
     * 注解验证测试
     *
     * @param o
     */
    public static <T> void notBlankListByKey(Object o, Class<T> clazz) {
        Field[] declaredFields = o.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            boolean annotationPresent = declaredField.isAnnotationPresent(NotBlankListByKey.class);
            if (annotationPresent) {
                NotBlankListByKey annotation = declaredField.getAnnotation(NotBlankListByKey.class);
                String message = annotation.message();
                System.out.println("message: " + message);

                declaredField.setAccessible(true);

                String name = declaredField.getName();
                System.out.println(name);

                List<?> fieldValue = null;
                try {
                    Object valueObject = declaredField.get(o);
                    Assert.isNull(valueObject, name + "不能为空！");

                    fieldValue = (List<T>) declaredField.get(o);
                    Assert.isTrue(fieldValue.size() > 0, name + "不能为空！！");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                System.out.println(fieldValue);
                fieldValue.stream().forEach(e -> Assert.isTrue(!isEmptyIfStr(e), name + "不能为空!!!"));

            }
        }
    }

    /**
     * if null,return true
     *
     * @param valueList
     * @return
     */
    public static boolean isEmptyInList(List<?> valueList) {
        if (CollectionUtils.isEmpty(valueList)) {
            return true;
        }
        return valueList.stream().anyMatch(e -> isEmptyIfStr(e));
    }


    /**
     * <p>如果对象是字符串是否为空串，空的定义如下：</p><br>
     * <ol>
     *     <li>{@code null}</li>
     *     <li>空字符串：{@code ""}</li>
     * </ol>
     *
     * <p>例：</p>
     * <ul>
     *     <li>{@code StrUtil.isEmptyIfStr(null)     // true}</li>
     *     <li>{@code StrUtil.isEmptyIfStr("")       // true}</li>
     *     <li>{@code StrUtil.isEmptyIfStr(" \t\n")  // false}</li>
     *     <li>{@code StrUtil.isEmptyIfStr("abc")    // false}</li>
     * </ul>
     *
     * <p>注意：该方法与 {@link #isBlankIfStr(Object)} 的区别是：该方法不校验空白字符。</p>
     *
     * @param obj 对象
     * @return 如果为字符串是否为空串
     */
    public static boolean isEmptyIfStr(Object obj) {
        if (null == obj) {
            return true;
        } else if (obj instanceof CharSequence) {
            return 0 == ((CharSequence) obj).length();
        }
        return false;
    }

    /**
     * <p>如果对象是字符串是否为空白，空白的定义如下：</p>
     * <ol>
     *     <li>{@code null}</li>
     *     <li>空字符串：{@code ""}</li>
     *     <li>空格、全角空格、制表符、换行符，等不可见字符</li>
     * </ol>
     *
     * <p>例：</p>
     * <ul>
     *     <li>{@code StrUtil.isBlankIfStr(null)     // true}</li>
     *     <li>{@code StrUtil.isBlankIfStr("")       // true}</li>
     *     <li>{@code StrUtil.isBlankIfStr(" \t\n")  // true}</li>
     *     <li>{@code StrUtil.isBlankIfStr("abc")    // false}</li>
     * </ul>
     *
     * <p>注意：该方法与 {@link #isEmptyIfStr(Object)} 的区别是：
     * 该方法会校验空白字符，且性能相对于 {@link #isEmptyIfStr(Object)} 略慢。</p>
     *
     * @param obj 对象
     * @return 如果为字符串是否为空串
     */
    public static boolean isBlankIfStr(Object obj) {
        if (null == obj) {
            return true;
        } else if (obj instanceof CharSequence) {
            return isBlank((CharSequence) obj);
        }
        return false;
    }

    public static boolean isNotBlank(CharSequence str) {
        return false == isBlank(str);
    }

    public static boolean isBlank(CharSequence str) {
        final int length;
        if ((str == null) || ((length = str.length()) == 0)) {
            return true;
        }

        for (int i = 0; i < length; i++) {
            // 只要有一个非空字符即为非空字符串
            if (false == isBlankChar(str.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     * 是否空白符<br>
     * 空白符包括空格、制表符、全角空格和不间断空格<br>
     *
     * @param c 字符
     * @return 是否空白符
     * @see Character#isWhitespace(int)
     * @see Character#isSpaceChar(int)
     */
    public static boolean isBlankChar(char c) {
        return isBlankChar((int) c);
    }

    /**
     * 是否空白符<br>
     * 空白符包括空格、制表符、全角空格和不间断空格<br>
     *
     * @param c 字符
     * @return 是否空白符
     * @see Character#isWhitespace(int)
     * @see Character#isSpaceChar(int)
     */
    public static boolean isBlankChar(int c) {
        return Character.isWhitespace(c)
                || Character.isSpaceChar(c)
                || c == '\ufeff'
                || c == '\u202a'
                || c == '\u0000'
                // issue#I5UGSQ，Hangul Filler
                || c == '\u3164'
                // Braille Pattern Blank
                || c == '\u2800'
                // MONGOLIAN VOWEL SEPARATOR
                || c == '\u180e';
    }
}
